package com.brandservice.service;


import static com.brandservice.utils.SearchUtil.am;

import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;

import androidx.annotation.Nullable;

import com.brandservice.IBrandServiceAIDL;
import com.brandservice.BrandResult;
import com.brandservice.TaskResult;
import com.brandservice.TaskTarget;
import com.brandservice.utils.DetectorUtil;
import com.brandservice.utils.IndexUtil;
import com.brandservice.utils.SearchUtil;
import com.brandservice.utils.SnowFlakeUtil;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import kotlin.io.ByteStreamsKt;

import org.pytorch.IValue;
import org.pytorch.MemoryFormat;
import org.pytorch.Module;
import org.pytorch.Tensor;
import org.pytorch.torchvision.TensorImageUtils;
public class BrandService extends Service {
    private static final String TAG = "BrandService";

    private static final SnowFlakeUtil worker = new SnowFlakeUtil(1,1,1);

   public static Module module_ori = null;
    //用于静态加载图片库的数据

    private DetectorUtil detectorUtil;

    private IBinder iBinder = new IBrandServiceAIDL.Stub() {

        @Override
        public BrandResult getBrandResult(ParcelFileDescriptor pfd) throws RemoteException {
            Log.d(TAG, "[sendImageAndGetResult]");
            Long start = System.currentTimeMillis();
            FileDescriptor fileDescriptor = pfd.getFileDescriptor();
            FileInputStream fis = new FileInputStream(fileDescriptor);
            byte[] data = ByteStreamsKt.readBytes((InputStream)fis);
            Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

            BrandResult brandResult = new BrandResult();

            brandResult.setTraceId(worker.nextId());
            Date date = new Date();
            @SuppressLint("SimpleDateFormat") SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
            brandResult.setCreateTime(dateFormat.format(date));

            /** detection **/
            TaskResult detectorResult = detectorUtil.startDetection(bitmap);
            brandResult.setDetectResult(detectorResult);
            /** detection **/

            /** search **/
            if (detectorResult.getTargets() != null && !detectorResult.getTargets().isEmpty()) {
                bitmap = detectorResult.getTargets().get(0).getImage();
            }

            List<Bitmap> bitmaps = new ArrayList<>();
            bitmaps.add(bitmap);
            TaskResult searchResult = SearchUtil.startSearch(bitmaps);
            brandResult.setSearchResult(searchResult);
            Log.i(TAG, searchResult.getTargets().toString());
            /** search **/

            try{
                fis.close();
            }catch (IOException e){

            }
            Long end = System.currentTimeMillis();
            brandResult.setTotalCostTime((int) (end-start));
            Log.d(TAG, "[sendImageAndGetResult]: "+brandResult.toString());
            return brandResult;
        }
        @Override
        public BrandResult getBrandResultWithBitmap(Bitmap bitmap) throws RemoteException {
            return getResult(bitmap);
        }

        private BrandResult getResult(Bitmap bitmap){
            Long start = System.currentTimeMillis();
            BrandResult brandResult = new BrandResult();
            brandResult.setTraceId(worker.nextId());
            Date date = new Date();
            @SuppressLint("SimpleDateFormat") SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd :hh:mm:ss");
            brandResult.setCreateTime(dateFormat.format(date));

            /** detection **/
            TaskResult detectorResult = detectorUtil.startDetection(bitmap);
            brandResult.setDetectResult(detectorResult);
            /** detection **/

            TaskResult searchResult = new TaskResult();
            /** search **/
            List<Bitmap> bitmaps = new ArrayList<>();
            if (detectorResult.getTargets() != null && !detectorResult.getTargets().isEmpty()) {
                System.out.println("检测结果不为空");
                for(TaskTarget target: detectorResult.getTargets()){
                    bitmaps.add(target.getImage());
                }
            }
            else {System.out.println("检测结果为空"); bitmaps.add(bitmap);}

            searchResult = SearchUtil.startSearch(bitmaps);
            brandResult.setSearchResult(searchResult);
            Log.i(TAG, searchResult.getTargets().toString());
            /** search **/


            Long end = System.currentTimeMillis();
            brandResult.setTotalCostTime((int) (end-start));
            Log.d("[BrandService]", brandResult.toString());
            return brandResult;
        }


    };





    @Override
    public void onCreate() {
        super.onCreate();
        detectorUtil = new DetectorUtil(getResources().getAssets(), BrandService.this);

        SearchUtil.am = getResources().getAssets();

        try {
            module_ori = Module.load(assetFilePath(this,"resnet101_test_1023_nocuda.pt"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        Log.e(TAG, "[onCreate]");
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return iBinder;
    }


    public String assetFilePath(Context context, String assetName) throws IOException {
        File file = new File(context.getFilesDir(), assetName);
        if (file.exists() && file.length() > 0) {
            System.out.println(file.getAbsolutePath());
            return file.getAbsolutePath();
        }

        try (@SuppressLint({"NewApi", "LocalSuppress"}) InputStream is = context.getAssets().open(assetName)) {
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                try (OutputStream os = Files.newOutputStream(file.toPath())) {
                    byte[] buffer = new byte[4 * 1024];
                    int read;
                    while ((read = is.read(buffer)) != -1) {
                        os.write(buffer, 0, read);
                    }
                    os.flush();
                }
            }
            return file.getAbsolutePath();
        }
    }


}
